using System;
using System.Collections.Generic;
using System.Text;
using Jbe.TestSuite.Infrastructure.Interface.Services;
using System.Windows.Forms;
using Microsoft.Practices.CompositeUI;
using Jbe.TestSuite.Infrastructure.Interface.Constants;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.Utility;
using Jbe.CABExtension;

namespace Jbe.TestSuite.Infrastructure.Module.Services
{
    public class EditManager : IEditManager
    {
        private IEditHandler activeHandler;
        private Dictionary<object, IEditHandler> handlers = new Dictionary<object,IEditHandler>();

        private WorkItem workItem;
        private IAdapterFactoryCatalog<IEditHandler> factoryCatalog;
        
        [ServiceDependency]
        public WorkItem WorkItem
        {
            set 
            { 
                workItem = value;
                UpdateEditCommands();
            }
        }

        [ServiceDependency]
        public IAdapterFactoryCatalog<IEditHandler> FactoryCatalog
        {
            set { factoryCatalog = value; }
        }

        public EditManager()
        {
            Application.Idle += new EventHandler(ApplicationIdle);
        }

        public void Register(IEditHandler editHandler)
        {
            Guard.ArgumentNotNull(editHandler, "editHandler");
            editHandler.Enter += new EventHandler(EditEnter);
            editHandler.Leave += new EventHandler(EditLeave);
        }

        public void Register(object uiElement)
        {
            IEditHandler handler = factoryCatalog.GetFactory(uiElement).GetAdapter(uiElement);
            handlers.Add(uiElement, handler);
            Register(handler);
        }

        public void Deregister(IEditHandler editHandler)
        {
            Guard.ArgumentNotNull(editHandler, "editHandler");
            editHandler.Enter -= EditEnter;
            editHandler.Leave -= EditLeave;
        }

        public void Deregister(object uiElement)
        {
            if (handlers.ContainsKey(uiElement))
            {
                Deregister(handlers[uiElement]);
                handlers.Remove(uiElement);
            }
        }

        private void UpdateEditCommands()
        {
            bool enabled = (activeHandler != null);

            SetCommandStatus(CommandNames.Undo, enabled && activeHandler.CanUndo);
            SetCommandStatus(CommandNames.Redo, enabled && activeHandler.CanRedo);
            SetCommandStatus(CommandNames.Cut, enabled && activeHandler.CanCut);
            SetCommandStatus(CommandNames.Copy, enabled && activeHandler.CanCopy);
            SetCommandStatus(CommandNames.Paste, enabled && activeHandler.CanPaste);
            SetCommandStatus(CommandNames.Delete, enabled && activeHandler.CanDelete);
            SetCommandStatus(CommandNames.SelectAll, enabled && activeHandler.CanSelectAll);
        }

        private void SetCommandStatus(string commandName, bool enabled)
        {
            workItem.Commands[commandName].Status = (enabled) ? CommandStatus.Enabled : CommandStatus.Disabled; 
        }

        #region Command and Event handler

        private void EditEnter(object sender, EventArgs e)
        {
            Guard.TypeIsAssignableFromType(sender.GetType(), typeof(IEditHandler), "sender");

            activeHandler = (IEditHandler)sender;
            UpdateEditCommands();
        }

        private void EditLeave(object sender, EventArgs e)
        {
            activeHandler = null;
            UpdateEditCommands();
        }

        private void ApplicationIdle(object sender, EventArgs e)
        {
            UpdateEditCommands();
        }

        [CommandHandler(CommandNames.Undo)]
        public void Undo(object sender, EventArgs e)
        {
            activeHandler.Undo();
        }

        [CommandHandler(CommandNames.Redo)]
        public void Redo(object sender, EventArgs e)
        {
            activeHandler.Redo();
        }

        [CommandHandler(CommandNames.Cut)]
        public void Cut(object sender, EventArgs e)
        {
            activeHandler.Cut();
        }

        [CommandHandler(CommandNames.Copy)]
        public void Copy(object sender, EventArgs e)
        {
            activeHandler.Copy();
        }

        [CommandHandler(CommandNames.Paste)]
        public void Paste(object sender, EventArgs e)
        {
            activeHandler.Paste();
        }

        [CommandHandler(CommandNames.Delete)]
        public void Delete(object sender, EventArgs e)
        {
            activeHandler.Delete();
        }

        [CommandHandler(CommandNames.SelectAll)]
        public void SelectAll(object sender, EventArgs e)
        {
            activeHandler.SelectAll();
        }

        #endregion
    }
}
